package monitor

import (
	"context"
	"encoding/json"
	"smart-flow/server/config"
	"smart-flow/server/executor"
	"smart-flow/server/logger"
	"smart-flow/server/proto"
	"smart-flow/server/redis"
	"smart-flow/server/utils"
	"time"

	"go.uber.org/zap"
)

type ContainerData struct {
	proto.ExchangeReq
}

func SaveContainer(req *proto.ExchangeReq) {
	data, err := json.Marshal(req)
	if err != nil {
		return
	}
	redis.RDB.HSet(context.Background(), utils.GenIspAnyKey(config.FlowContainerKey, req.Isp), req.MonitorIp, data)
	for _, uid := range req.ExpiredV4 {
		executor.ExecutingInstance(req.Isp).DelExecutor(uid)
	}
	for _, uid := range req.ExpiredV6 {
		executor.ExecutingInstance(req.Isp).DelExecutor(uid)
	}
	lengthV4 := len(req.ExpiredV4)
	lengthV6 := len(req.ExpiredV6)
	for i := 0; i < lengthV4; i += 50 {
		redis.RDB.HDel(context.Background(), utils.GenIspAnyKey(config.FlowManageKey, req.Isp), req.ExpiredV4[i:min(lengthV4, i+50)]...)
	}
	for i := 0; i < lengthV6; i += 50 {
		redis.RDB.HDel(context.Background(), utils.GenIspAnyKey(config.FlowManageKey, req.Isp), req.ExpiredV6[i:min(lengthV6, i+50)]...)
	}
	logger.Logger.Info("[交换] 删除过期的Executor",
		zap.String("ip", req.MonitorIp), zap.String("isp", config.GetIspHuman(req.Isp)), zap.Int("v4", lengthV4), zap.Int("v6", lengthV6))
}

func GetContainersByIsp(isp string) []*ContainerData {
	data, err := redis.RDB.HVals(context.Background(), utils.GenIspAnyKey(config.FlowContainerKey, isp)).Result()
	if err != nil {
		return nil
	}
	var containers []*ContainerData
	for _, v := range data {
		var container ContainerData
		_ = json.Unmarshal([]byte(v), &container)
		if time.Now().Unix()-container.Timestamp > 60 {
			continue
		}
		containers = append(containers, &container)
	}
	return containers
}

func GetDownBandwidthByIsp(isp string) int64 {
	var sumDownBandwidth int64 = 0
	data, err := redis.RDB.HVals(context.Background(), utils.GenIspAnyKey(config.FlowContainerKey, isp)).Result()
	if err != nil {
		return -1
	}
	var container ContainerData
	for _, v := range data {
		_ = json.Unmarshal([]byte(v), &container)
		if time.Now().Unix()-container.Timestamp > 60 {
			continue
		}
		sumDownBandwidth += int64(container.DownTotal)
	}
	return sumDownBandwidth
}

func GetOnlineCountByIsp(isp string) int64 {
	containers := GetContainersByIsp(isp)
	if len(containers) == 0 {
		return 0
	}
	var onlineCount int64
	for _, co := range containers {
		onlineCount += co.OnlineV4Count
		onlineCount += co.OnlineV6Count
	}
	return onlineCount
}
